package com.franklin.ideaplugin.maphelper.completion.result.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.franklin.ideaplugin.api.utils.ClassUtils;
import com.franklin.ideaplugin.api.utils.psi.PsiClassUtils;
import com.franklin.ideaplugin.api.utils.psi.PsiTypeUtils;
import com.franklin.ideaplugin.maphelper.beans.colmember.IColMember;
import com.franklin.ideaplugin.maphelper.beans.colmember.StringColMember;
import com.franklin.ideaplugin.maphelper.completion.result.IMapLookupElementBuilder;
import com.franklin.ideaplugin.maphelper.icons.PluginIcons;
import com.franklin.ideaplugin.maphelper.utils.FastJsonUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Ye Junhui
 * @since 2024/3/7
 */
public class FastJsonMapLookupElementBuilder implements IMapLookupElementBuilder {

    public final static FastJsonMapLookupElementBuilder INSTANCE = new FastJsonMapLookupElementBuilder();

    /**
     * 前缀映射
     */
    private Map<PsiType, String> typePrefixMap = Maps.newHashMap();

    {
        typePrefixMap.put(PsiTypes.booleanType(), "getBoolean");
        typePrefixMap.put(PsiTypes.byteType(), "getByte");
        typePrefixMap.put(PsiTypes.shortType(), "getShort");
        typePrefixMap.put(PsiTypes.intType(), "getInteger");
        typePrefixMap.put(PsiTypes.longType(), "getLong");
        typePrefixMap.put(PsiTypes.floatType(), "getFloat");
        typePrefixMap.put(PsiTypes.doubleType(), "getDouble");
    }


    /**
     * 模板
     */
    private final static String LOOKUP_TEMPLATE = "%s(%s)";

    @Override
    public boolean support(PsiExpression psiExpression) {
        PsiType psiType = psiExpression.getType();
        PsiClassType psiClassType = (PsiClassType) psiType;
        //类名
        String className = psiClassType.resolve().getQualifiedName();

        return FastJsonUtils.FAST_JSON_OBJECT_CLASSES.contains(className);
    }

    @Override
    public @NotNull List<LookupElementBuilder> buildLookupElement(PsiExpression psiExpression, IColMember colMember) {
        String keyText = colMember.getKeyText();
        String typeText = colMember.getValueClassSimple();

        List<String> lookupStringList = buildLookupString(psiExpression, colMember);
        if (CollectionUtil.isEmpty(lookupStringList)) {
            return Lists.newArrayList();
        }
        List<LookupElementBuilder> result = lookupStringList.stream()
                .map(lookupString -> {
                    String typeString = typeText;
                    if (lookupString.contains("JSONArray")){
                        typeString = "JSONArray";
                    } else if (lookupString.contains("JSONObject")) {
                        typeString = "JSONObject";
                    }
                    LookupElementBuilder lookupElementBuilder = LookupElementBuilder.create(lookupString)
                            .withIcon(PluginIcons.PLUGIN_ICON)
                            .withTypeText(typeString);
                    return lookupElementBuilder;
                })
                .collect(Collectors.toList());
        return result;
    }

    /**
     * 构建提示
     *
     * @param psiExpression
     * @param colMember
     * @return
     */
    private List<String> buildLookupString(PsiExpression psiExpression, IColMember colMember) {
        String keyText = colMember.getKeyText();
        String valueClass = colMember.getValueClass();
        PsiType psiType = PsiTypeUtils.getPsiType(valueClass, psiExpression.getProject());
        //基本数据类型
        if (typePrefixMap.containsKey(psiType)) {
            String prefix = typePrefixMap.get(psiType);
            return Lists.newArrayList(
                    String.format(LOOKUP_TEMPLATE, prefix, keyText)
            );
        }
        if (!PsiClassType.class.isInstance(psiType)) {
            return Collections.emptyList();
        }
        PsiClassType psiClassType = (PsiClassType) psiType;
        PsiClass psiClass = psiClassType.resolve();
        if (Objects.isNull(psiClass)) {
            psiClass = PsiClassUtils.findPsiClass(
                    psiExpression.getProject(),
                    ClassUtils.getClassNameWithoutGeneric(valueClass)
            );
        }
        if (Objects.isNull(psiClass)){
            return Collections.emptyList();
        }
        //BigDecimal
        PsiClass bigDecimalClass = PsiClassUtils.findPsiClass(psiExpression.getProject(), BigDecimal.class);
        if (PsiClassUtils.isInheritorOrEquals(bigDecimalClass, psiClass)) {
            String prefix = "getBigDecimal";
            return Lists.newArrayList(
                    String.format(LOOKUP_TEMPLATE, prefix, keyText)
            );
        }
        //BigInteger
        PsiClass bigIntegerClass = PsiClassUtils.findPsiClass(psiExpression.getProject(), BigInteger.class);
        if (PsiClassUtils.isInheritorOrEquals(bigIntegerClass, psiClass)) {
            String prefix = "getBigInteger";
            return Lists.newArrayList(
                    String.format(LOOKUP_TEMPLATE, prefix, keyText)
            );
        }
        //String
        PsiClass stringClass = PsiClassUtils.findPsiClass(psiExpression.getProject(), String.class);
        if (PsiClassUtils.isInheritorOrEquals(stringClass, psiClass)) {
            String prefix = "getString";
            List<String> result = Lists.newArrayListWithCapacity(2);
            result.add(
                    String.format(LOOKUP_TEMPLATE, prefix, keyText)
            );
            if (colMember instanceof StringColMember) {
                StringColMember stringColMember = (StringColMember) colMember;
                String valueString = stringColMember.getValue().toString();
                if (FastJsonUtils.isValidJsonObject(valueString)) {
                    result.add(String.format(LOOKUP_TEMPLATE, "getJSONObject", keyText));
                } else if (FastJsonUtils.isValidJsonArray(valueString)) {
                    result.add(String.format(LOOKUP_TEMPLATE, "getJSONArray", keyText));
                }
            }
            return result;
        }
        //map
        if (PsiClassUtils.isJavaMapClass(psiClass)) {
            String prefix = "getJSONObject";
            return Lists.newArrayList(
                    String.format(LOOKUP_TEMPLATE, prefix, keyText)
            );
        }
        //list
        PsiClass listClass = PsiClassUtils.findPsiClass(psiExpression.getProject(), List.class);
        if (PsiClassUtils.isInheritorOrEquals(listClass, psiClass)) {
            String prefix = "getJSONArray";
            return Lists.newArrayList(
                    String.format(LOOKUP_TEMPLATE, prefix, keyText)
            );
        }

        //其它
        return Lists.newArrayList(
                String.format("getObject(%s,%s.class)", keyText, psiClassType.getName())
        );
    }

}
